#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>

#include "opencv_util.h"

const char*
depth2str(int depth)
{
    const char *depthStr = 0;
    switch (depth) {
    case CV_8U: depthStr = "CV_8U"; break;
    case CV_8S: depthStr = "CV_8S"; break;
    case CV_16U: depthStr = "CV_16U"; break;
    case CV_16S: depthStr = "CV_16S"; break;
    case CV_32S: depthStr = "CV_32S"; break;
    case CV_32F: depthStr = "CV_32F"; break;
    case CV_64F: depthStr = "CV_64F"; break;
    default: depthStr = "UNKNOWN";
    }
    return depthStr;
}

/*
 * 计算矩阵 left 与 right 各元素乘积的和.
 * @param left 要求:CV_8UC1;
 * @Param right 要求: CV_64FC1;并且 left,right 具有一样的大小.
 */
static double
sumOfProduct(const cv::Mat &left,const cv::Mat &right)
{
    double sum = 0;
    cv::MatConstIterator_<uchar> leftIter = left.begin<uchar>();
    cv::MatConstIterator_<double> rightIter = right.begin<double>();
    cv::MatConstIterator_<uchar> const leftEndIter = left.end<uchar>();
    for(; leftIter != leftEndIter; ++leftIter,++rightIter) 
        sum += *leftIter * *rightIter;
    return sum;
}


/*
 * 计算图像 m 与模板 t 的空间相关,结果存放在 m 中.
 * @param m 要求:CV_8UC1 类型.
 * @param t 要求:CV_64FC1 类型,m 行 n 列,并且 m,n 都是奇数.
 * @return 空间相关结果,即 m 的引用.
 */
cv::Mat&
correlation(cv::Mat &m,const cv::Mat &t)
{
    int const a = (t.rows - 1) / 2;
    int const b = (t.cols - 1) / 2;
    cv::Mat m1(m.rows + 2 * a,m.cols + 2 * b,CV_8UC1);
    cv::copyMakeBorder(m,m1,a,a,b,b,cv::BORDER_REPLICATE);
   
    for (int r = a,rMax = a + m.rows; r < rMax; ++r) {
        for (int c = b,cMax = b + m.cols; c < cMax; ++c) {
            double tmp = sumOfProduct(m1(cv::Rect(c - b,r - a,t.cols,t.rows)),t);
            m.at<uchar>(r - a,c - b) = cv::saturate_cast<uchar>(tmp);
        } 
    }

    return m;
}

